Skip to content

Added cardano connector plugin #1636

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 53 commits into
base: main
Choose a base branch
from

Conversation

SupernaviX
Copy link
Contributor

@SupernaviX SupernaviX commented Feb 8, 2025

Proposed changes

Adds a cardano connector plugin to firefly core. This connector interacts with the firefly-cardanoconnect service from firefly-cardano.


Types of changes

  • Bug fix
  • New feature added
  • Documentation Update

Please make sure to follow these points

  • I have read the contributing guidelines.
  • I have performed a self-review of my own code or work.
  • I have commented my code, particularly in hard-to-understand areas.
  • My changes generates no new warnings. (uh
  • My Pull Request title is in format < issue name > eg Added links in the documentation.

firefly


Other Information

The Cardano connector and implementation is still a work in progress; in particular we need documentation and tests. However, it works well enough to demo, and I'd like to merge this relatively soon so that people can run it without building firefly-core from a branch, or downloading an image from a private repo.

@SupernaviX SupernaviX requested a review from a team as a code owner February 8, 2025 00:13
Signed-off-by: Simon Gellis <[email protected]>
Signed-off-by: Simon Gellis <[email protected]>
Copy link

codecov bot commented Feb 8, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.96%. Comparing base (36b4179) to head (71673fd).

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #1636    +/-   ##
========================================
  Coverage   99.95%   99.96%            
========================================
  Files         339      342     +3     
  Lines       29782    30457   +675     
========================================
+ Hits        29770    30445   +675     
  Misses          8        8            
  Partials        4        4            

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@EnriqueL8 EnriqueL8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! It's fantastic to see 👏🏼

Some initial thoughts and will follow up with more thorough review after playing around with it 😃

Comment on lines 390 to 393
func (c *Cardano) GenerateErrorSignature(ctx context.Context, event *fftypes.FFIErrorDefinition) string {
// TODO: impl
return ""
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be interested to understand more how errors are reported in Cardano from smart contract

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cardano smart contract doesn't report errors right now, only events. I don't understand the difference between errors and events, and I couldn't find any code in other plugins which streamed errors from the connector.

I've copied the "event signature" code into this function, but that's just a guess at what it's supposed to do. I'd want to see how consumers actually use events to be more confident about that.

Comment on lines 542 to 550
if !isBatch {
var receipt common.BlockchainReceiptNotification
_ = json.Unmarshal(msgBytes, &receipt)

err := common.HandleReceipt(ctx, "", c, &receipt, c.callbacks)
if err != nil {
l.Errorf("Failed to process receipt: %+v", msgTyped)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that this is heavily inspired from FFTM and the evm plugin - I would recommend in the future moving to a durable event stream here where the receipts have to be ack'd back as part of a batch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was using EVM, Tezos, and FFTM as references for how the eventstream is supposed to work (trying my best to make Cardano match the semantics of other connectors). It looked like other connectors assume that every message in a batch is an event, not a receipt.

I think it makes sense to use resilient ack-ing for everything, but I'm a little wary about inventing semantics for it in this plugin that nothing else is using.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed - probably as a follow up. I'm building a framework at moment to allow for resilient ack-ing and get confirmation from FireFly core it has processed things correctly

Copy link
Contributor

@EnriqueL8 EnriqueL8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was reminded yesterday of the key being mandatory today as part of deploying a contract and it doesn't make sense for Cardano as the connector has used that API to run a off-chain dApp that is responsible of building Cardano TX and indexing state. Raised a discussion on Discord https://discord.com/channels/905194001349627914/928377875827154984/1349704667524763689


## Create the stack

A Cardano stack can be run in two different ways; with a firefly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A Cardano stack can be run in two different ways; with a firefly
A Cardano stack can be run in two different ways with Hyperledger FireFly

@EnriqueL8
Copy link
Contributor

EnriqueL8 commented Mar 13, 2025

Sorry I tagged a comment in a linked PR as Fixes and it automatically closed this PR when the fix was merged

@EnriqueL8
Copy link
Contributor

Timeout error in a Cardano unit test

2025-03-15T04:08:58.2090672Z time="2025-03-15T04:08:13Z" level=info msg="Event stream: es12345 (topic=topic1/ns1)" proto=cardano
2025-03-15T04:08:58.2091695Z time="2025-03-15T04:08:13Z" level=info msg="WS ws://127.0.0.1:38187/ws connected" proto=cardano
2025-03-15T04:08:58.2092715Z time="2025-03-15T04:08:13Z" level=error msg="Message unexpected: map[bad:receipt]" proto=cardano role=event-loop
2025-03-15T04:08:58.2093959Z time="2025-03-15T04:08:13Z" level=error msg="Message cannot be parsed as JSON: different kind of bad batch" proto=cardano role=event-loop
2025-03-15T04:08:58.2095178Z time="2025-03-15T04:08:13Z" level=error msg="Unexpected message in batch: map[]" proto=cardano role=event-loop
2025-03-15T04:08:58.2096586Z time="2025-03-15T04:08:13Z" level=error msg="Message cannot be parsed as JSON: invalid character '!' looking for beginning of value\n!json" proto=cardano role=event-loop
2025-03-15T04:08:58.2098375Z time="2025-03-15T04:08:13Z" level=error msg="Message unexpected: map[not:a reply]" proto=cardano role=event-loop
2025-03-15T04:08:58.2099475Z time="2025-03-15T04:08:13Z" level=error msg="Message unexpected: 42" proto=cardano role=event-loop
2025-03-15T04:08:58.2100729Z time="2025-03-15T04:08:13Z" level=info msg="WS ws://127.0.0.1:38187/ws closed: websocket: close 1006 (abnormal closure): unexpected EOF" proto=cardano
2025-03-15T04:08:58.2102030Z time="2025-03-15T04:08:13Z" level=warning msg="WS ws://127.0.0.1:38187/ws connect attempt 1 failed [-1]: " proto=cardano
2025-03-15T04:08:58.2103411Z time="2025-03-15T04:08:13Z" level=warning msg="WS ws://127.0.0.1:38187/ws connect attempt 2 failed [-1]: " proto=cardano
2025-03-15T04:08:58.2104487Z time="2025-03-15T04:08:13Z" level=warning msg="WS ws://127.0.0.1:38187/ws connect attempt 3 failed [-1]: " proto=cardano
2025-03-15T04:08:58.2105552Z time="2025-03-15T04:08:14Z" level=warning msg="WS ws://127.0.0.1:38187/ws connect attempt 4 failed [-1]: " proto=cardano
2025-03-15T04:08:58.2106606Z time="2025-03-15T04:08:16Z" level=warning msg="WS ws://127.0.0.1:38187/ws connect attempt 5 failed [-1]: " proto=cardano
2025-03-15T04:08:58.2107893Z time="2025-03-15T04:08:20Z" level=warning msg="WS ws://127.0.0.1:38187/ws connect attempt 6 failed [-1]: " proto=cardano
2025-03-15T04:08:58.2108945Z time="2025-03-15T04:08:28Z" level=warning msg="WS ws://127.0.0.1:38187/ws connect attempt 7 failed [-1]: " proto=cardano
2025-03-15T04:08:58.2109990Z time="2025-03-15T04:08:44Z" level=warning msg="WS ws://127.0.0.1:38187/ws connect attempt 8 failed [-1]: " proto=cardano
2025-03-15T04:08:58.2113860Z coverage: 29.3% of statements
2025-03-15T04:08:58.2114274Z panic: test timed out after 45s
2025-03-15T04:08:58.2114707Z running tests:
2025-03-15T04:08:58.2115101Z 	TestInitAndStartWithCardanoConnect (45s)
2025-03-15T04:08:58.2115440Z 
2025-03-15T04:08:58.2115582Z goroutine 26 [running]:
2025-03-15T04:08:58.2115949Z testing.(*M).startAlarm.func1()
2025-03-15T04:08:58.2116605Z 	/opt/hostedtoolcache/go/1.22.12/x64/src/testing/testing.go:2366 +0x385
2025-03-15T04:08:58.2117428Z created by time.goFunc
2025-03-15T04:08:58.2117937Z 	/opt/hostedtoolcache/go/1.22.12/x64/src/time/sleep.go:177 +0x2d

Copy link
Contributor

@EnriqueL8 EnriqueL8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SupernaviX This is looking really good! A few small comments, thanks for the detailed docs :)


CONTRACT_PATH="/path/to/your/dapp"
FIREFLY_URL="http://localhost:5000"
firefly-cardano-deploy --contract-path "$CONTRACT_PATH" --firefly-url "$FIREFLY_URL"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, probably as a follow up adding this to the FireFly CLI would be great :) We have similar deploy and install commands in for Fabric and EVM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would definitely be more convenient than asking users to install some standalone tool. But part of deploying these contracts is compiling rust code to webassembly. Would it be OK for the FireFly CLI to shell out to cargo?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh that is good point, as all these tools are in Rust! I think it would be fine

- Start sending events
- For the Subscription named `sample-contract`
- On the `default` namespace
- Automatically "ack" each event which will let FireFly immediately send the next event when available
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We recommend not using autoack as it's safer for application to manual ack once they have processed the event

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what the other contract readmes say to do. Are there instructions for how to consume this kind of API without autoack somewhere?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there should be in the subscription section - let me pull it out

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does need some cleaning up maybe

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a note about autoack below this. I do think autoack behavior makes sense for initial setup/experimentation, as long as users know not to leave it on.

func (nm *networkMap) generateCardanoAddressVerifier(identity *core.Identity, verifier *core.Verifier) *VerificationMethod {
return &VerificationMethod{
ID: verifier.Hash.String(),
Type: "PaymentVerificationKeyShelley_ed25519", // hope that it's safe to assume we always use Shelley
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that is correct

Comment on lines +2 to +11
"cardanoconnect": {
"image": "ghcr.io/hyperledger/firefly-cardanoconnect",
"tag": "v0.4.1",
"sha": "78b1008bd62892f6eda197b5047d94e61621d0f06b299422ff8ed9b34ee5ce50"
},
"cardanosigner": {
"image": "ghcr.io/hyperledger/firefly-cardanosigner",
"tag": "v0.4.1",
"sha": "d0b76613ccc70ff63e68b137766eb009d589489631cee6aabf2b45e33a1ca5d3"
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might need updating again

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the latest published versions, I just confirmed that with manifestgen.sh. We could probably cut new versions of those soon, but I'd rather not block this big long-lived PR on it.

@EnriqueL8
Copy link
Contributor

I think it needs an 0.813 sqlite-3.44.2-r1: 0.813 breaks: world[sqlite=3.44.2-r0] update

@SupernaviX
Copy link
Contributor Author

I think it needs an 0.813 sqlite-3.44.2-r1: 0.813 breaks: world[sqlite=3.44.2-r0] update

Probably, but it's also failing due to the crypto audit. So I'm just waiting until the build passes on main, so that I can merge main and get a working build (and then address your comments).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants